<?php
// +----------------------------------------------------------------------
// | A3Mall
// +----------------------------------------------------------------------
// | Copyright (c) 2020 http://www.a3-mall.com All rights reserved.
// +----------------------------------------------------------------------
// | Author: xzncit <158373108@qq.com>
// +----------------------------------------------------------------------

namespace app\common\model\users;

use app\common\model\base\A3Mall;

class WalletDetail extends A3Mall{

    protected $name = "wallet_detail";

    protected $type = [

    ];

    /**
     * 类型列表
     *类型：根据代码设置类型；1-49 设置为收入；51- 99 设置为支出；101-150 设置为冻结
     */
    const TYPE_LIST = [
        'jobFrozen'     => [101,'发任务冻结金额'],     // key 外部传入；[类型ID,resaon 说明,金额类型]；注意：id是可以重复的，主要是同ID不同用途说明，目前未用到
        'jobUnfrozen'   => [102,'发任务解冻金额'],     // key 外部传入；[类型ID,resaon 说明,金额类型]；注意：id是可以重复的，主要是同ID不同用途说明，目前未用到
        'buyIssueLevel' => [51,'购买发单等级'],
        'buyAcceptLevel'=> [52,'购买接单等级'],
        'issueCost'     => [53,'发任务花费'],
        'acceptIn'      => [49,'接任务进账'],
        'withDraw'      => [54,'提现'],
        'recharge'      => [48,'充值']
    ];



    /**
     * 获取用户余额
     * @param $userId
     */
    public function getBalanceCount($userDetails)
    {
        if(!$userDetails = is_integer($userDetails)?$this->findOne($userDetails):$userDetails) {
            throw new \Exception('用户钱包数据不存在');
        }

        return bcadd($userDetails['withdraw_amount'],$userDetails['non_withdraw_amount'],2) - 0;
    }

    /**
     * 通过用户 ID 获取用户钱包数据
     * @param $userId
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function findOne($userId) {
        $result = $this->where(['user_id'=>$userId])->find()->toArray();
        return $result;
    }


    /**
     * 通过钱包增加详情
     * @param $data 详细参数
     * @param $type 类型，注意是 string
     */
    public function recordAddFromWallet($data,$type)
    {
        $typeDetails = static::TYPE_LIST[$type];
        $insertData = [
            'user_id'   => 0,
            'amount'    => 0,
            'related_id'    => 0,
            'related_pid'   => 0,
        ];
        foreach($insertData as $key=>$value) {
            $insertData[$key] = array_key_exists($key,$data)?$data[$key]:$value;
        }
        $insertData = array_merge($insertData,[
            'type'  => $typeDetails[0],
            'resaon'    => $typeDetails[1],
            'create_time'   => time(),
        ]);
        if(!$this->insert($insertData)){
            throw new \Exception('系统繁忙，请稍后再试');
        }
        return true;
    }


    /**
     * 添加详情，然后修改用户钱包
     * @param $walletDetails 个人账户资金详情
     * @param $amount 金额
     * @param $type  详情类型
     * @param $data 其他数据
     * @throws \Exception
     */
    public function recordAddToWallet($walletDetails,$amount,$type,$data){
        if($walletDetails['withdraw_amount'] <0 || $walletDetails['non_withdraw_amount'] <0) {
            throw new \Exception('用户金额异常，请联系管理员核实');
        }

        // 验证消费金额
        $checkConsumptionAmountFunc = function () use($walletDetails,$amount) {
            if($amount > 0 || bcadd(bcadd($walletDetails['withdraw_amount'],$walletDetails['non_withdraw_amount'],2),$amount,2) < 0){
                throw new \Exception('剩余金额不够消费');
            }
        };

        $withdrawAmount = $amount;  //可提现金额
        $nonWithdrawAmount =0;  // 不可提现金额
        switch($type) { //根据类型判断 可用及不可用金额

            case 'jobFrozen':
            case 'jobUnfrozen':
                throw new \Exception($type . '不可走该接口');
            case 'issueCost':   // 消费
            case 'buyIssueLevel':   // 优先使用不可用金额
            case 'buyAcceptLevel':
                $checkConsumptionAmountFunc();
                $nonWithdrawAmount = bcadd($walletDetails['non_withdraw_amount'],$amount,2) >0?$amount:bcsub(0,$walletDetails['non_withdraw_amount'],2);
                $withdrawAmount = bcsub($withdrawAmount,$nonWithdrawAmount,2) - 0;
                break;
            case 'withDraw':    // 提现
                if($amount > 0){
                    throw new \Exception('提现金额有误');
                }
                if(bcadd($walletDetails['withdraw_amount'],$amount,2) < 0){
                    throw new \Exception('提现金额不能大于可提现金额');
                }
                break;
            case 'recharge':    // 充值
                $nonWithdrawAmount = $withdrawAmount;
                $withdrawAmount = 0;
                break;
            case 'acceptIn':    //进账
                break;
            default:
        }
        // 添加消费详情
        $this->recordAddFromWallet(array_merge($data,[
            'amount'    => $amount,
            'user_id'   => $walletDetails['user_id'],
        ]),$type);
        // 修改用户钱包
        (new Wallet())->updateFromWalletDetaisl($walletDetails['user_id'],$walletDetails['ver'],$withdrawAmount,$nonWithdrawAmount);
        return true;
    }


    /**
     * 通过任务ID统计消耗
     * @param $jobId
     */
    public static function countRecordByJobId($jobId)
    {
        $typeList = array_combine(array_keys(static::TYPE_LIST),array_column(static::TYPE_LIST,0));
        $result = [
            'jobFrozen' => static::where([['type','=',$typeList['jobFrozen']],['related_id','=',$jobId]])->sum('amount'),   // 冻结金额
            'acceptIn' => static::where([['type','=',$typeList['acceptIn']],['related_pid','=',$jobId]])->sum('amount'),    // 支出金额
        ];
        return $result;
    }

    public static function getTypeList()
    {
        return array_column(array_values(static::TYPE_LIST),1,0);
    }

    public function users(){
        return $this->hasOne(Users::class,"id","user_id")
            ->bind(['username'])->joinType("INNER");
    }

    public function getList($condition,$size=10,$page=1){
        // echo $this->withJoin(["users"])->where($condition)->fetchSql(true)->select();exit();
        $count = $this->withJoin(["users"])->where($condition)->count();
        $data = $this->withJoin(["users"])->where($condition)->order('wallet_detail.id','DESC')->paginate($size);

        return [
            "count"=>$count,
            "data"=>array_map([$this,'format'],$data->items())
        ];
    }

    public function getCreateTimeTextAttr($value,$data){
       return date("Y-m-d H:i:s",$data['create_time']);
    }

    protected function format($value)
    {
        $value->create_time_text=$value->create_time_text;
        return $value;
    }
}

